home *** CD-ROM | disk | FTP | other *** search
- /*
- File: DialogWindow.cp
-
- Contains: Implementation of a base class for Modeless Dialogs
-
- Written by: Dave Falkenburg
-
- Copyright: © 1993-1995 by Dave Falkenburg, all rights reserved.
-
- Change History (most recent first):
-
- <8> 1/20/95 DRF Deal with new menu command changes. Also fixed bug where we
- weren’t disposing of TDialogWindows using DisposeDialog.
- <7> 11/16/94 DRF Added explicit #include <Traps.h> for latest universal headers.
- <6> 11/12/94 DRF Fix a bug in EventFilter method which returned false even if a
- dialog item was hit.
- <5> 11/8/94 DRF We have better menu handling methods, so use them instead of the
- old “DoEditMenu” method.
- <3> 10/17/94 DRF ItemHit is now a pure-virtual method. Fixed bugs in DoEditMenu.
- Call StdFilterProc inside EventFilter to handle ok, cancel,
- and I-beam cursor tracking.
- <3> 9/27/94 DRF AppLib.h is now Sprocket.h
- <2> 9/9/94 DRF Reordered headers and removed redundant #includes. Also fixed
- constants in DoEditMenu.
- */
-
- #include "Sprocket.h"
- #include "DialogWindow.h"
- #include "StandardMenus.h"
- #include <Traps.h>
-
- TDialogWindow::TDialogWindow(DialogType dialogType, DialogTemplateID theDialogTemplate)
- {
- fTemplateID = theDialogTemplate;
- fIsDialogWindow = true;
-
- this->CreateWindow(((dialogType == kModalDialog) ? kModalWindow : kNormalWindow));
- }
-
-
- WindowRef
- TDialogWindow::MakeNewWindow(WindowRef behindWindow)
- {
- return GetDialogWindow ( GetNewDialog(fTemplateID,nil, (WindowRef) behindWindow));
- }
-
-
- Boolean
- TDialogWindow::Close(void)
- {
- // We have to do this in case all we are the last window open
- // We don't want to leave the menu items enabled
-
- gMenuBar->EnableCommand ( cCut, false );
- gMenuBar->EnableCommand ( cCopy, false );
- gMenuBar->EnableCommand ( cPaste, false );
- gMenuBar->EnableCommand ( cClear, false );
- gMenuBar->EnableCommand ( cSelectAll, false );
-
- return TWindow::Close();
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////////
- //
- // EventFilter strategy for Dialog Window
- //
- // Because of the need to patch and unpatch FrontWindow when calling IsDialogEvent
- // and DialogSelect, only do these things when a Modless Dialog is the frontmost
- // window. (e.g., it’s event filter is active)
- //
- // NOTE: We always pass events through, except when an item has been hit.
- //
- // You may be thinking that it is easier to just rewrite the Dialog Manager in
- // this program. You’re probably right.
-
- pascal WindowRef FrontWindowPatchForDialogs();
-
-
- pascal WindowRef
- FrontWindowPatchForDialogs()
- {
- return TWindow::FrontNonFloatingWindow();
- }
-
-
- #define uppFrontWindowPatchProcInfo (kPascalStackBased | RESULT_SIZE(SIZE_CODE(sizeof(WindowRef))))
-
- UniversalProcPtr FrontWindowPatchUPP
- = (UniversalProcPtr) NewRoutineDescriptor((ProcPtr) &FrontWindowPatchForDialogs,uppFrontWindowPatchProcInfo,GetCurrentISA());
-
-
- Boolean
- TDialogWindow::EventFilter(EventRecord *theEvent)
- {
- GrafPtr oldPort;
- UniversalProcPtr oldFrontWindow = GetToolboxTrapAddress(_FrontWindow);
- DialogRef aDialog;
- Boolean eventHasBeenGobbled = false;
- short aDialogItem = 0;
- short oldWindowKind;
-
- // Don’t snarf keypresses meant for menus
- if ((theEvent->what == keyDown) && (theEvent->modifiers & cmdKey))
- return false;
-
- GetPort(&oldPort);
- SetGrafPortOfDialog ( GetDialogRef ());
-
- // Patch in our version of FrontWindow so that IsDialogEvent will do the right
- // thing. DialogManager should check both frontmost floating and frontmost
- // non-floating windows, however we don’t support floating dialogs.
- SetToolboxTrapAddress(FrontWindowPatchUPP,_FrontWindow);
-
- // Jam the windowKind of our dialog window back to dialogKind so that the
- // Dialog Manager can recognize our window as a dialog window.
- oldWindowKind = GetWindowKind(fWindow);
- SetWindowKind(fWindow, dialogKind);
-
-
- if (IsDialogEvent(theEvent))
- {
- // It’s definitely a dialog event, so let the DialogMgr figure things out.
- //
- // We first let StdFilterProc have a crack at it so that the default
- // and cancel buttons are properly processed (as well as automagic text
- // cursor tracking).
-
- // If StdFilterProc didn’t find anything to do, go ahead and call
- // DialogSelect to figure out if the user did anything important.
-
- // Isn’t this alot easier than what Inside Mac says to do?
-
- eventHasBeenGobbled = StdFilterProc( GetDialogRef (),theEvent,&aDialogItem);
-
- // Give the window a chance to pre-process the event
- // This is useful for people who want to implement read-only text items (for example)
-
- if (eventHasBeenGobbled == false)
- eventHasBeenGobbled = this->FilterDialogEvent ( theEvent, &aDialogItem );
-
- // Let the dialog manager deal with the event
- if (eventHasBeenGobbled == false)
- eventHasBeenGobbled = DialogSelect(theEvent,&aDialog,&aDialogItem);
- }
-
- // Restore the windowKind
- SetWindowKind(fWindow, oldWindowKind);
-
- // Put FrontWindow back the way it really belongs
- SetToolboxTrapAddress((UniversalProcPtr) oldFrontWindow,_FrontWindow);
-
- if (eventHasBeenGobbled)
- {
- this->ItemHit(aDialogItem); // Call user’s method to deal with a hit
- eventHasBeenGobbled = true;
- }
-
- SetPort(oldPort);
-
- return eventHasBeenGobbled;
- }
-
-
- Boolean
- TDialogWindow::FilterDialogEvent(EventRecord */*theEvent*/, short *itemHit )
- {
- *itemHit = 0;
- return false; // Event not handled
- }
-
-
- void
- TDialogWindow::Activate(Boolean activating)
- {
- EventRecord fakeEvent;
-
- /* (De)activates are NOT automagically handled because our floating
- * windows prevent real activate events from ever being generated
- * for any non-floaters windows.
- *
- * Our strategy is to fool the dialog manager into thinking that
- * things are still fine by passing it a fake (de)activate event.
- *
- * Luckily, we don’t have to patch FrontWindow to make DialogSelect
- * work for activate and update events.
- */
-
- OSEventAvail(0,&fakeEvent); // Get an intialized, but otherwise empty event record
-
- fakeEvent.what = activateEvt;
- fakeEvent.message = (unsigned long) GetDialogRef ();
- if (activating)
- fakeEvent.modifiers |= activeFlag;
- else
- fakeEvent.modifiers &= ~activeFlag;
-
- // Pass event on to DialogSelect
-
- DialogRef aDialog;
- short aDialogItem;
-
- (void) DialogSelect(&fakeEvent,&aDialog,&aDialogItem);
- }
-
-
- void
- TDialogWindow::Draw(void)
- {
- // Automagically handled by Dialog Manager when we are
- // the frontmost window, but not at other times because
- // we only set the windowKind to dialogKind inside our
- // EventFilter (which is only active when we are frontmost).
- RgnHandle update = NewRgn ();
- GetWindowUpdateRgn ( fWindow, update );
- UpdateDialog ( GetDialogRef (), update );
- DisposeRgn ( update );
- }
-
-
- void
- TDialogWindow::Click(EventRecord * /* anEvent */)
- {
- /* The only time this method is called is to handle a click
- * when the dialog window isn’t frontmost. All other times,
- * DialogSelect will do everything for us.
- *
- * If our dialog contains useritems with the ability to
- * be the source of a drag we’d need to start drag tracking
- * in here.
- */
-
- this->Select();
- }
-
-
- void
- TDialogWindow::AdjustMenusBeforeMenuSelection(void)
- {
- TEHandle teh = GetDialogTextEdit ( GetDialogRef ());
- Boolean validSelection = teh != NULL && ( (*teh)->selStart != (*teh)->selEnd );
-
- gMenuBar->EnableCommand ( cCut, validSelection );
- gMenuBar->EnableCommand ( cCopy, validSelection );
- gMenuBar->EnableCommand ( cPaste, true ); // we really should check the scrap
- gMenuBar->EnableCommand ( cClear, validSelection );
-
- gMenuBar->EnableCommand ( cSelectAll, teh != NULL );
- }
-
-
- Boolean
- TDialogWindow::DoMenuCommand(MenuCommandID command)
- {
- DialogRef theDialog = GetDialogRef ();
-
- switch (command)
- {
- case cUndo:
- break;
-
- case cCut:
- DialogCut(theDialog);
- return true;
-
- case cCopy:
- DialogCopy(theDialog);
- return true;
-
- case cPaste:
- DialogPaste(theDialog);
- return true;
-
- case cClear:
- DialogDelete(theDialog);
- return true;
-
- case cSelectAll:
- SelectDialogItemText ( theDialog, GetDialogKeyboardFocusItem ( theDialog ), 0, 32767 );
- return true;
-
- default:
- break;
- }
-
- // If we don't handle it, then let the super-class handle it
- return TWindow::DoMenuCommand ( command );
- }
-